home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Best of MacTutor - S…e Code for Volumes 1 to 5
/
The Best of MacTutor - Source Code for Volume 1-5 (Wayzata Technology)(6031)(1990).bin
/
Source Code
/
#21 (Jun 87)
/
forth source
/
Permanent DA
< prev
Wrap
Text File
|
1987-04-06
|
12KB
|
501 lines
( A multi-window, multi-menu, permanent desk accessory )
( J. Langowski March 87 )
only forth also assembler also mac
INCLUDE" ::general defs"
BINARY
0000110111101010 CONSTANT DAEmask
HEX
A20 CONSTANT MBarEnable
A88 CONSTANT CloseOrnHook
( *** close intercept routine *** )
HEX
1B4 CONSTANT SystemTask
HEADER inter.start
HEADER DAName
DC.B 10,0,'Mach 2 DA'
HEADER trapaddr
DC.L 0
header inter.stack 40 allot
CODE setup.inter.stack
LEA -8(PC),A6 ( local stack grows downward from here )
RTS
END-CODE
: inter
call frontwindow windowkind + @
2 <> IF
['] trapaddr @ SystemTask call SetTrapAddress
['] DAName call OpenDeskAcc drop
THEN
;
CODE intercept
MOVEM.L A0-A4/A6/D0-D7,-(A7)
JSR setup.inter.stack
JSR inter
MOVEM.L (A7)+,A0-A4/A6/D0-D7
MOVE.L trapaddr,-(A7)
RTS
END-CODE
HEADER inter.end
( for exportation )
' trapaddr ' inter.start - CONSTANT *trapaddr
' intercept ' inter.start - CONSTANT *inter
DECIMAL
( *** start of desk accessory main code *** )
header testDA ( marker for writing to DRVR resource )
header drvrFlags 2 allot
header drvrdelay 2 allot
header drvrEMask 2 allot
header drvrMenu 2 allot
header drvrOpen 2 allot
header drvrPrime 2 allot
header drvrCtl 2 allot
header drvrStatus 2 allot
header drvrClose 2 allot
header drvrname 32 allot
( *** main desk accessory routines *** )
header temprect 8 allot
header SizeRect 8 allot ( grow size limits )
header NewSize 4 allot ( for SizeWindow )
header penLoc 4 allot ( pen location )
header tempString 256 allot ( for numeric conversion etc. )
header ButtonHdl 4 allot ( for storage of control handle )
header closeflag 4 allot ( for storage of close status )
header CurMenuList 4 allot ( menu list temporary storage )
header CloseOrn 4 allot ( CloseOrnHook temporary storage )
header window2 4 allot ( second DA window )
header showflag 4 allot ( state of 2nd window, 1: visible, 0: not)
header myRes0 4 allot ( local res ID=0 offset )
header temp 4 allot ( general purpose )
: @mouse { | mousept -- point }
^ mousept call getMouse mousept ;
: cl ( WPtr -- ) portrect + call eraserect ;
: tp call drawstring ;
: crd ['] penLoc call getpen
10 ( horizontal boundary )
['] penLoc w@ 12 +
call moveto
;
: realclose { | dCtlEntry }
MOVE.L A1,-(A6)
-> dCtlEntry
MOVE.L A4,-(A6)
CASE
dCtlEntry dCtlWindow + @ OF
['] closeflag off
dCtlEntry dCtlRefNum + w@ call CloseDeskAcc
ENDOF
['] window2 @ OF 5 call sysbeep ENDOF
ENDCASE
;
( *** event-handling routines *** )
: >oldMBar
['] CurMenuList @ call SetMenuBar
call DrawMenuBar
0 MBarEnable w!
;
: activate-handler { DAWind event-rec | menuID -- }
['] myRes0 @ -> menuID
CloseOrnHook @ ['] CloseOrn !
['] realclose CloseOrnHook !
event-rec modifiers + w@ 1 and
IF ( window activated )
call frontwindow CASE DAWind OF
menuID MBarEnable w!
call GetMenuBar ['] CurMenuList !
call ClearMenuBar
menuID call getRMenu 0 call InsertMenu
menuID 1+ call getRMenu 0 call InsertMenu
call drawMenuBar
ENDOF
ENDCASE
ELSE >oldMBar ( window deactivated )
['] CloseOrn @ CloseOrnHook !
THEN
;
: update-handler { DAWind event-rec | -- }
['] penLoc call GetPen
DAWind CALL BeginUpdate
DAWind cl
DAWind CALL DrawGrowIcon
DAWind CALL DrawControls
DAWind CALL EndUpdate
['] penLoc 2+ w@ ['] penLoc w@ call moveto ( restore pen position )
;
: invalSize { gPort | b r -- }
gPort 4 + w@ -> b
gPort 6 + w@ -> r
['] temprect r 16 - 0 r b call setrect
['] temprect call invalrect
['] temprect 0 b 16 - r b call setrect
['] temprect call invalrect
;
: mousedn-handler
{ DCtlEntry DAWind event-rec |
whereM DAPort whichCtl whichWind mouseloc menuID menuRes wKind -- }
['] myRes0 @ -> menuID
DAWind portrect + -> DAPort
event-rec where + @ dup -> whereM -> mouseloc
^ mouseloc call GlobalToLocal
whereM ^ whichWind call FindWindow drop ( result code )
whichWind CASE
DAWind OF
DAWind windowkind + dup w@ -> wKind
8 swap w! ( set to application-created window )
whereM ^ whichWind call FindWindow
CASE
inGrow OF
DAPort invalSize
DAWind whereM ['] SizeRect call GrowWindow
DAWind swap unpack swap -1 call sizewindow
DAPort invalSize
ENDOF
inZoomIn OF
DAWind whereM 7 call TrackBox
IF DAPort invalSize
DAWind 7 0 call ZoomWindow THEN
ENDOF
inZoomOut OF
DAWind whereM 8 call TrackBox
IF DAPort invalSize
DAWind 8 0 call ZoomWindow THEN
ENDOF
mouseloc DAWind ^ whichCtl call FindControl
IF
whichCtl mouseLoc 0 call TrackControl
IF ['] window2 @
1 ['] showflag @ - ['] showflag !
['] showflag @
IF call showwindow ELSE call hidewindow THEN
THEN
ELSE
" Mouse down" tp crd
THEN
ENDCASE
wKind DAWind windowkind + w! ( reset to DA window )
ENDOF
['] window2 @ OF 5 call sysbeep ENDOF
ENDCASE
;
: update-cursor { DAWind | -- }
@mouse DAWind portrect + call PtInRect
IF call InitCursor THEN
;
: getDrvrID { dCtlEntry | -- num }
dCtlEntry dCtlRefNum + w@ l_ext
1+ negate
;
: ownResID ( resID drvrID )
5 shl + -16384 +
;
: install.intercept { dCtlEntry | procHdl -- }
"proc ['] myRes0 @ call GetResource -> procHdl
SystemTask call GetTrapAddr
procHdl @ *trapaddr + !
procHdl @ *inter + SystemTask call SetTrapAddr
;
: Open { DCtlEntry ParamBlockRec | DAWind DAWind2 Res0 oldPort -- }
^ oldPort call GetPort
dCtlEntry dCtlWindow + @
0= IF ( not open already )
['] closeflag on
['] showflag off
0 dCtlEntry getDrvrID ownResID -> Res0
Res0 ['] myRes0 !
"proc Res0 call GetResource
call ReleaseResource ( remove from sysheap )
Res0 dCtlEntry DCtlMenu + w!
( menu ref has to be updated )
Res0 0 0 call getNewWindow -> DAWind
DAWind dCtlEntry dCtlWindow + ! ( store window pointer )
DAWind dCtlEntry dCtlRefNum + w@ swap windowKind + w!
Res0 1+ 0 0 call getNewWindow -> DAWind2
DAWind2 ['] window2 !
DAWind2 dCtlEntry dCtlRefNum + w@ swap windowKind + w!
DAWind call setport
['] sizerect 50 50 500 320 call setrect
10 40 call moveto
Res0 DAWind call GetNewControl ['] ButtonHdl !
oldPort call setPort
THEN
;
: Close { DCtlEntry ParamBlockRec | -- }
dCtlEntry dCtlWindow +
dup @ call DisposWindow 0 swap ! ( so that Open will work again )
['] window2 @ call disposWindow
['] closeflag @ IF DCtlEntry install.intercept THEN
MBarEnable w@ IF >oldMBar THEN
;
: Ctl { DCtlEntry ParamBlockRec | DAWind oldPort event-rec menuID menuRes -- }
^ oldPort call GetPort
dCtlEntry dCtlWindow + @ dup -> DAWind call setport
4 call textfont 9 call textsize
DCtlEntry DCtlMenu + w@ l_ext -> menuID
ParamBlockRec csCode + w@ l_ext
CASE
goodBye OF 10 call sysbeep
dCtlEntry ParamBlockRec Close
['] closeflag off ENDOF
accEvent OF
ParamBlockRec csParam + @ -> event-rec
event-rec what + w@
CASE
mousedn-evt OF
DCtlEntry DAWind event-rec mousedn-handler ENDOF
keydn-evt OF DAWind cl
DAWind call DrawGrowIcon
DAWind call DrawControls
10 40 call moveto " Key down." tp crd
ENDOF
autokey-evt OF ENDOF
update-evt OF
DAWind event-rec update-handler ENDOF
disk-evt OF ENDOF
activate-evt OF
DAWind event-rec activate-handler ENDOF
network-evt OF ENDOF
driver-evt OF ENDOF
ENDCASE
ENDOF
accRun OF ['] window2 @ dup call setport cl
4 call textfont 9 call textsize
20 10 call moveto
['] temp call readdatetime drop
['] temp @ -1 ['] tempstring call IUTimeString
['] tempstring tp
ENDOF
accCursor OF DAWind update-cursor ENDOF
accMenu OF
ParamBlockRec csParam + @ unpack -> menuRes
l_ext
CASE menuID OF
menuRes
CASE 1 OF " Item1-1!" tp crd ENDOF
2 OF " Item1-2!" tp crd ENDOF
3 OF " Item1-3!" tp crd ENDOF
4 OF " Item1-4!" tp crd ENDOF
6 OF " Item1-6!" tp crd ENDOF
ENDCASE ENDOF
menuID 1+ OF
menuRes
CASE 1 OF " Item2-1!" tp crd ENDOF
2 OF " Item2-2!" tp crd ENDOF
3 OF " Item2-3!" tp crd ENDOF
4 OF " Item2-4!" tp crd ENDOF
6 OF " Item2-6!" tp crd ENDOF
ENDCASE
ENDOF
ENDCASE
0 call HiLiteMenu
ENDOF
accUndo OF ENDOF
accCut OF ENDOF
accCopy OF ENDOF
accPaste OF ENDOF
accClear OF ENDOF
ENDCASE
oldport call setPort
;
: DrStatus { DCtlEntry ParamBlockRec | -- }
;
: Prime { DCtlEntry ParamBlockRec | -- }
;
( *** glue routines *** )
header local.stack 1000 allot
CODE setup.local.stack
LEA -8(PC),A6 ( local stack grows downward from here )
RTS
END-CODE
CODE DAOpen
MOVEM.L A0-A1,-(A7)
setup.local.stack
MOVE.L A1,-(A6)
MOVE.L A0,-(A6)
Open
CLR.L D0
MOVEM.L (A7)+,A0-A1
RTS END-CODE
CODE DAClose
MOVEM.L A0-A1,-(A7)
setup.local.stack
MOVE.L A1,-(A6)
MOVE.L A0,-(A6)
Close
CLR.L D0
MOVEM.L (A7)+,A0-A1
RTS END-CODE
CODE DACtl
MOVEM.L A0-A1,-(A7)
setup.local.stack
MOVE.L A1,-(A6)
MOVE.L A0,-(A6)
Ctl
CLR.L D0
MOVEM.L (A7)+,A0-A1
MOVE.L JioDone,-(A7)
RTS END-CODE
CODE DAStatus
MOVEM.L A0-A1,-(A7)
setup.local.stack
MOVE.L A1,-(A6)
MOVE.L A0,-(A6)
DrStatus
CLR.L D0
MOVEM.L (A7)+,A0-A1
RTS END-CODE
CODE DAPrime
MOVEM.L A0-A1,-(A7)
setup.local.stack
MOVE.L A1,-(A6)
MOVE.L A0,-(A6)
Prime
CLR.L D0
MOVEM.L (A7)+,A0-A1
RTS END-CODE
header endDA ( *** code written to DRVR resource ends here *** )
( *** initialization routines *** )
: setFlags ['] drvrFlags w! ;
: setDelay ['] drvrDelay w! ;
: setEMask ['] drvrEMask w! ;
: setMenuID ['] drvrMenu w! ;
: setOpen ['] drvrOpen w! ;
: setPrime ['] drvrPrime w! ;
: setCtl ['] drvrCtl w! ;
: setStatus ['] drvrStatus w! ;
: setClose ['] drvrClose w! ;
: setName { addr len | target -- }
['] drvrName -> target
len target c!
addr target 1+
len 31 > if 31 else len then
cmove
;
( write resource to file )
: $create-res ( str-addr - errcode )
call CreateResFile
call ResError L_ext
;
: $open-res { addr | refNum - refNum or errcode }
addr call OpenResFile -> refNum
call ResError L_ext
?dup IF ELSE refNum THEN
;
: close-res ( refNum - errcode )
call CloseResFile
call ResError L_ext
;
: make-res { addr len rtype ID name | -- }
addr len call PtrToHand
abort" Could not create resource handle"
rtype ID name call AddResource
;
: write-out { filename | refnum -- }
filename $create-res abort" That resource file already exists"
filename $open-res
dup 0< abort" Open resource file failed"
-> refnum
refnum call UseResFile
['] testDA ['] endDA over -
"drvr 12 " Mach 2 DA" make-res
['] inter.start ['] inter.end over -
"proc -16000 " Mach 2 DA" make-res
"proc -16000 call GetResource
dup 80 call SetResAttrs ( 64: sysheap + 16: locked )
call ChangedResource
refnum close-res abort" Could not close resource file"
;
: init-DA
( initialize offsets )
['] DAOpen ['] testDA - setOpen
['] DAPrime ['] testDA - setPrime
['] DACtl ['] testDA - setCtl
['] DAStatus ['] testDA - setStatus
['] DAClose ['] testDA - setClose
( initialize driver name )
" Mach 2 DA" count setname
( initialize driver flags, NeedLock, NeedTime, NeedGoodBye, CtlEnable )
[ hex ] 7400 setFlags [ decimal ]
( initialize delay time )
60 setDelay
( initialize event mask, events recommended in IM )
DAEMask setEMask
( initialize menu ID, local ID=0 for DRVR ID=12 )
-16000 setMenuID ( careful! this field will NOT be changed
by the DA Mover when ID is changed )
;
: make-DA
init-DA
" Mach2 DA.rsrc" $delete drop
" Mach2 DA.rsrc" write-out
;